package com.galaxy.payment.utils;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeCloseModel;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.galaxy.common.core.exception.ServiceException;
import com.galaxy.payment.api.RemoteOrderService;
import com.galaxy.payment.api.RemoteUserService;
import com.galaxy.payment.config.AliPayConfig;
import com.galaxy.payment.domain.OrderBo;
import com.galaxy.payment.domain.bo.AccountFlowBo;
import com.galaxy.payment.domain.bo.PaymentBo;
import com.galaxy.payment.domain.vo.PaymentRecordVo;
import com.galaxy.payment.service.IAccountFlowService;
import com.galaxy.payment.service.IPaymentRecordService;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Base64Utils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 支付宝支付工具类
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AliPayUtils {

    private final AliPayConfig aliPayConfig;
    private AlipayClient alipayClient;

    @Autowired
    private IPaymentRecordService paymentRecordService;

    @Autowired
    private IAccountFlowService iAccountFlowService;

    @Autowired
    private RemoteOrderService remoteOrderService;

    @Autowired
    private RemoteUserService remoteUserService;

    /**
     * 获取支付宝客户端
     */
    public AlipayClient getAlipayClient() {
        if (alipayClient == null) {
            alipayClient = new DefaultAlipayClient(
                aliPayConfig.getGatewayUrl(),
                aliPayConfig.getAppId(),
                aliPayConfig.getPrivateKey(),
                aliPayConfig.getFormat(),
                aliPayConfig.getCharset(),
                aliPayConfig.getPublicKey(),
                aliPayConfig.getSignType()
            );
        }
        return alipayClient;
    }

    /**
     * 创建支付宝支付订单
     */
    public String createPay(String outTradeNo, String subject, BigDecimal totalAmount) {
        try {
            AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
            request.setNotifyUrl(aliPayConfig.getNotifyUrl());
            request.setReturnUrl(aliPayConfig.getReturnUrl());

            AlipayTradePagePayModel model = new AlipayTradePagePayModel();
            model.setOutTradeNo(outTradeNo);
            model.setSubject(subject);
            model.setTotalAmount(totalAmount.toString());
            model.setProductCode("FAST_INSTANT_TRADE_PAY");
            request.setBizModel(model);

            AlipayTradePagePayResponse response = getAlipayClient().pageExecute(request);
            if (response.isSuccess()) {
                return response.getBody();
            } else {
                throw new ServiceException("创建支付宝支付订单失败：" + response.getSubMsg());
            }
        } catch (AlipayApiException e) {
            log.error("创建支付宝支付订单失败", e);
            throw new ServiceException("创建支付宝支付订单失败：" + e.getMessage());
        }
    }

    /**
     * 查询支付宝支付订单
     */
    public AlipayTradeQueryResponse queryPay(String outTradeNo) {
        try {
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            AlipayTradeQueryModel model = new AlipayTradeQueryModel();
            model.setOutTradeNo(outTradeNo);
            request.setBizModel(model);

            AlipayTradeQueryResponse response = getAlipayClient().execute(request);
            if (!response.isSuccess()) {
                throw new ServiceException("查询支付宝支付订单失败：" + response.getSubMsg());
            }
            return response;
        } catch (AlipayApiException e) {
            log.error("查询支付宝支付订单失败", e);
            throw new ServiceException("查询支付宝支付订单失败：" + e.getMessage());
        }
    }

    /**
     * 关闭支付宝支付订单
     */
    public void closePay(String outTradeNo) {
        try {
            AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
            AlipayTradeCloseModel model = new AlipayTradeCloseModel();
            model.setOutTradeNo(outTradeNo);
            request.setBizModel(model);

            AlipayTradeCloseResponse response = getAlipayClient().execute(request);
            if (!response.isSuccess()) {
                throw new ServiceException("关闭支付宝支付订单失败：" + response.getSubMsg());
            }
        } catch (AlipayApiException e) {
            log.error("关闭支付宝支付订单失败", e);
            throw new ServiceException("关闭支付宝支付订单失败：" + e.getMessage());
        }
    }

    /**
     * 申请支付宝退款
     */
    public AlipayTradeRefundResponse refund(String outTradeNo, BigDecimal refundAmount, String reason) {
        try {
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            AlipayTradeRefundModel model = new AlipayTradeRefundModel();
            model.setOutTradeNo(outTradeNo);
            model.setRefundAmount(refundAmount.toString());
            model.setRefundReason(reason);
            request.setBizModel(model);

            AlipayTradeRefundResponse response = getAlipayClient().execute(request);
            if (!response.isSuccess()) {
                throw new ServiceException("申请支付宝退款失败：" + response.getSubMsg());
            }
            return response;
        } catch (AlipayApiException e) {
            log.error("申请支付宝退款失败", e);
            throw new ServiceException("申请支付宝退款失败：" + e.getMessage());
        }
    }

    /**
     * 查询支付状态
     *
     * @param orderNo 订单号
     * @return 交易状态
     */
    public String queryPayStatus(String orderNo) {
        try {
            log.info("开始查询订单状态，订单号：{}", orderNo);

            AlipayTradeQueryResponse response = queryPay(orderNo);
            log.info("支付宝查询订单响应：{}", response.getBody());

            if (response.isSuccess()) {
                String tradeStatus = response.getTradeStatus();
                log.info("订单状态：{}", tradeStatus);

                // 根据支付宝返回的交易状态判断订单是否支付成功
                if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                    return "PAID";
                } else if ("WAIT_BUYER_PAY".equals(tradeStatus)) {
                    return "UNPAID";
                } else if ("TRADE_CLOSED".equals(tradeStatus)) {
                    return "CLOSED";
                } else {
                    return "UNKNOWN";
                }
            } else {
                log.error("支付宝查询订单失败，错误码：{}，错误信息：{}",
                    response.getCode(), response.getMsg());

                // 处理交易不存在的错误
                if ("40004".equals(response.getCode()) && "ACQ.TRADE_NOT_EXIST".equals(response.getSubCode())) {
                    log.info("订单不存在或已关闭，订单号：{}", orderNo);
                    return "CLOSED";
                }

                return "ERROR";
            }
        } catch (Exception e) {
            log.error("查询订单状态失败", e);
            return "ERROR";
        }
    }

    /**
     * 验证回调签名
     *
     * @param params 回调参数
     * @return 验证结果
     */
    public boolean verifyCallback(Map<String, String> params) {
        try {
            boolean signVerified = AlipaySignature.rsaCheckV1(
                params,
                aliPayConfig.getPublicKey(),
                aliPayConfig.getCharset(),
                aliPayConfig.getSignType()
            );

            if (signVerified) {
                log.info("支付宝回调签名验证成功");
                return true;
            } else {
                log.error("支付宝回调签名验证失败");
                return false;
            }
        } catch (AlipayApiException e) {
            log.error("支付宝回调签名验证异常", e);
            return false;
        }
    }

    /**
     * 生成支付二维码
     * @param orderNo 订单号
     * @param amount  金额
     * @param subject 商品名称
     * @return 可直接生成二维码的支付URL
     */
    public String generatePayQrCode(String orderNo, String amount, String subject,String type) {
        try {
            log.info("开始创建支付宝支付订单，订单号：{}", orderNo);

            // 1. 创建支付请求
            AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();

            // 2. 设置支付参数

            // 3. 构造请求参数
            org.json.JSONObject bizContent = new JSONObject();
            bizContent.put("out_trade_no", orderNo);
            bizContent.put("total_amount",amount);
            bizContent.put("subject", subject);
            bizContent.put("body", Objects.equals(type, "充值") ? "充值" : "商品购买");
            bizContent.put("timeout_express", "15m");

            request.setBizContent(bizContent.toString());
            request.setNotifyUrl(aliPayConfig.getNotifyUrl());

            log.info("支付宝请求参数：{}", bizContent);

            AlipayTradePrecreateResponse response = getAlipayClient().execute(request);
            log.info("支付宝响应：{}", response.getBody());

            // 检查是否已经支付
            if (response.getCode().equals("40004") && response.getSubCode().equals("ACQ.TRADE_HAS_SUCCESS")) {
                log.info("订单已经支付，更新订单状态");
                PaymentRecordVo paymentRecord = paymentRecordService.getPaymentRecordByOrderNo(orderNo);
//                updateOrderStatus(orderNo, "PAID"); // 假设有一个方法用于更新订单状态
                AccountFlowBo accountFlowBo = new AccountFlowBo();
                accountFlowBo.setUserId(paymentRecord.getUserId());
                accountFlowBo.setOrderNo(orderNo);
                accountFlowBo.setFlowType(Objects.equals(type, "充值") ? 1 : 2);
                accountFlowBo.setAmount(Objects.equals(type, "充值")?paymentRecord.getPaymentAmount():paymentRecord.getPaymentAmount().negate());

                accountFlowBo.setBalance(BigDecimal.ZERO);
                accountFlowBo.setDescription(Objects.equals(type, "充值") ? "充值余额" : "支付宝购买商品");
                iAccountFlowService.insertByBo(accountFlowBo);


                PaymentBo updateBo = new PaymentBo();
                updateBo.setPayNo(paymentRecord.getPayNo());
                updateBo.setStatus(2); // 支付成功
                updateBo.setSuccessTime(new Date());
                paymentRecordService.updateByBo(updateBo);
                OrderBo orderBo =  new OrderBo();
                orderBo.setId(paymentRecord.getOrderId());
                orderBo.setPayType(4);
                orderBo.setStatus(2);
                orderBo.setOutTradeNo(paymentRecord.getPayNo());
                orderBo.setPayTime(LocalDateTime.now());
                remoteOrderService.edit(orderBo);

                return "ORDER_ALREADY_PAID";
            }

            if (response.isSuccess()) {
                String qrCode = response.getQrCode();
                log.info("生成二维码成功，二维码URL：{}", qrCode);

                // 确保返回完整的二维码URL
                if (!qrCode.startsWith("http")) {
                    qrCode = "https://qr.alipay.com/" + qrCode;
                }

                // 生成二维码图片
                String base64QrCode = generateQRCodeImage(qrCode);
                return base64QrCode;
            } else {
                log.error("支付宝预创建订单失败，错误码：{}，错误信息：{}",
                    response.getCode(), response.getMsg());
                throw new RuntimeException("支付宝预创建订单失败：" + response.getMsg());
            }
        } catch (AlipayApiException e) {
            log.error("创建支付宝支付订单失败", e);
            throw new ServiceException("创建支付宝支付订单失败：" + e.getMessage());
        } catch (Exception e) {
            log.error("创建支付宝支付订单失败", e);
            throw new RuntimeException("创建支付宝支付订单失败：" + e.getMessage());
        }
    }

    /**
     * 生成二维码图片并转换为Base64
     */
    private String generateQRCodeImage(String text) throws WriterException, IOException {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, 300, 300);

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        MatrixToImageWriter.writeToStream(bitMatrix, "PNG", outputStream);

        return "data:image/png;base64," + Base64Utils.encodeToString(outputStream.toByteArray());
    }

    /**
     * 生成Base64格式的支付二维码图片
     */
    public String generateBase64QrCode(String orderNo, String amount, String subject, String type) {
        try {
            // 1. 获取支付URL
            return generatePayQrCode(orderNo, amount, subject, type);

            // 2. 生成二维码图片
//            return QrCodeGenerator.generateBase64QrCode(payUrl, 300, 300);
        } catch (Exception e) {
            log.error("生成支付二维码失败", e);
            throw new ServiceException("生成支付二维码失败：" + e.getMessage());
        }
    }
}
